#![allow(dead_code)]

use slice_deque::SliceDeque;
use std::fs::File;
use std::io::BufWriter;
use std::io::Write;

mod bit_set;
use crate::bit_set::BitSet;

use SliceDeque as Container;

struct LFSR
{
	taps: Vec<u16>,
	register: Container<u8>,

	//Cached variables
	register_size: usize,
}

impl LFSR
{	
	fn new(taps: Vec<u16>, seed: Vec<u8>) -> Self
	{
		let mut tmp = Self {
			taps: taps,
			register: Container::with_capacity(seed.len() + 1),
			register_size: seed.len(),
		};
		for t in seed
		{
			tmp.register.push_front(t);
		}
		tmp
	}

	fn get_byte(&mut self) -> u8
	{
		let mut buffer: u8 = 0;

		for bit in 0..8
		{
			let mut shift_bit: bool = false;
			for tap in &self.taps
			{
				let tap: usize = (tap + bit).into();
				if tap >= (self.register_size * 8)
				{
					shift_bit ^= buffer.get_bit(tap % self.register_size);
				}
				else
				{
					let word_idx = tap / 8;
					let bit_idx = tap % 8;
					shift_bit ^= self.register[self.register_size - 1 - word_idx].get_bit(bit_idx);
				}
			}

			buffer.set_bit(bit.into(), shift_bit);
		}
		let tmp = self.register.pop_back().unwrap();
		self.register.push_front(buffer);
		tmp
	}

	fn discard(&mut self, count: usize)
	{
		for _i in 0..count
		{
			self.get_byte();
		}
	}
}

fn main() {
	let taps: Vec<u16> = vec![1, 2, 3, 5, 6, 8, 15,
							 19, 28, 33, 41, 55, 57,
							 68, 73, 84, 87, 95, 96,
							 101, 103, 107, 110, 112,
							 113, 115, 120, 123, 127];

	let seed: Vec<u8> = vec![0x64, 0xE9, 0x89, 0x1A,
							 0x5B, 0xC5, 0xDE, 0xE3,
							 0x29, 0x67, 0xD1, 0x02,
							 0x34, 0x45, 0xAA, 0x54];

	let mut lfsr = LFSR::new(taps, seed);

	let file_size: usize = 1024 * 1024; // 1MB

	let mut data_file = BufWriter::new(File::create("output.dat").unwrap());

	for _i in 0..file_size
	{
		let _ = data_file.write(&[lfsr.get_byte()]);
	}
}
